package com.weepal.pavement.mqtt.demo.analysis.resolver;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.weepal.pavement.mqtt.demo.analysis.Analysiser;
import com.weepal.pavement.mqtt.demo.util.CRC16Util;
import com.weepal.pavement.mqtt.demo.util.test;
import com.weepal.pavement.mqtt.demo.vo.DeviceField;
import com.weepal.pavement.mqtt.demo.vo.GatewayDatavo;
import com.weepal.pavement.mqtt.demo.vo.MqttDevices;

import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 字符串数据裁剪
 *
 * @author mawen
 */
public class StringCuttingResolver {

    private String msg;
    //    private MqttDevices devices;
    private DeviceField field;
    private int fieldSize;

    private StringCuttingResolver() {

    }

    public StringCuttingResolver(String msg, MqttDevices devices) {
        this.msg = msg;
//        this.devices = devices;
    }

    public ConcurrentHashMap<String, LinkedList<String>> resolve() throws JsonProcessingException {
        GatewayDatavo[] gatewayDatavos = resolve2Array();
        return msgCutting(gatewayDatavos);
    }

    private final static int STILLSTARTINDEX = 11;

    //判断数据是离线数据 or 时效数据
    public GatewayDatavo[] resolve2Array() throws JsonProcessingException {
        System.out.println(msg);
        if (msg.indexOf("still") != -1) {
            //离线消息，开头包含still，不能直接转json
            //例子 {"still":1,[{{"Data0":"49443030334f4b","Data1":"","Data2":"03034224474e524d432c3030303030342e3130302c562c303030302e30303030302c4e2c30303030302e30303030302c452c302e3030302c302e30302c3036303138302c2cc521"},"acc":1,"stamp":"2020-8-1 6:40:12"},
            //                {{"Data0":"01030400000000fa33","Data1":"02030400000000c933","Data2":"03034224474e524d432c3232343031382e3031322c562c303030302e30303030302c4e2c30303030302e30303030302c452c302e3030302c302e30302c3331303732302c2cbb69"},"acc":1,"stamp":"2020-8-1 6:40:21"}
            //                ]}
            String data = msg.substring(STILLSTARTINDEX, msg.length() - 1);
            return msg2Array(data);
        } else {
            //时效数据
            return msg2Array(msg);
        }
    }

    private final static String FLAG = "\\{\\{";
    private final static String REPLACEFLAG = "\\{\"datas\":\\{";

    //字符串数据转数组
    public GatewayDatavo[] msg2Array(String msg) throws JsonProcessingException {
        String v = msg.replaceAll(FLAG, REPLACEFLAG);
        ObjectMapper mapper = new ObjectMapper();
        GatewayDatavo[] gatewayDatavos = mapper.readValue(v, GatewayDatavo[].class);
        return gatewayDatavos;
    }

    //解析信息数组
    public ConcurrentHashMap<String, LinkedList<String>> msgCutting(GatewayDatavo[] vos) {
        MqttDevices devices = Analysiser.devicesThreadLocal.get();
        ConcurrentHashMap<String, DeviceField> fields = devices.getFields();
        ConcurrentHashMap<String, LinkedList<String>> result = new ConcurrentHashMap(8);
        for (GatewayDatavo vo : vos) {
            //获取信息
            Map<String, String> datas = vo.getDatas();
            for (Map.Entry<String, String> entry : datas.entrySet()) {
                String key = entry.getKey();
                this.field = fields.get(key);
                LinkedList<String> v = cutting(entry);
                if (null != v) {
                    result.put(field.getJsonKey(), v);
                }
            }
        }
        return result;
    }

    public LinkedList<String> cutting(Map.Entry<String, String> entry) {
        MqttDevices devices = Analysiser.devicesThreadLocal.get();
        String f = field.getReadFields();//获取对应的字段
        this.fieldSize = f.split(",").length;
        LinkedList<String> datas;
        if (devices.getIsModbus() == 1) {
            //如果是标准modbus协议
            //先校验crc校验码，通过再切除(保证数据的准确性)
            boolean b = CRC16Util.checkBuf(entry.getValue().getBytes());
            if (!b) {
                return null;
            }
            datas = dataCutting(entry.getValue(), field.getChangeType());//数据数组
        } else {
            //非modbus协议
            //直接默认最后四个字符是crc校验码，直接切除(不保证数据的准确性)
            datas = dataCutting(entry.getValue(), field.getChangeType());//数据数组
        }
        return datas;
    }

    /**
     * 去掉4位crc校验位，然后从后往前根据配置的数据长度取数据
     * 数据是从右往左解析(即和配置的字段的顺序相反)，所以使用头插，取数据从头取即可对上字段顺序
     *
     * @return
     */
    public LinkedList<String> dataCutting(String msg, int changeType) {
        String nocrc = msg.substring(0, msg.length() - 4);//去掉4位crc校验位
        LinkedList<String> result = new LinkedList<>();
        while (nocrc.length() >= field.getDataSize()) {
            String value = nocrc.substring(nocrc.length() - field.getDataSize());
            System.out.println(value);
            if (fieldSize == result.size()) {
                break;
            }
            if (changeType != 0) {
                value = test.hex2dec(value, changeType);
            }
            result.addFirst(value);
            nocrc = nocrc.substring(0, nocrc.length() - field.getDataSize());
        }
        return result;
    }

}
